package com.cea.papyrus.core;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.parts.GraphicalEditor;
import org.eclipse.ui.IEditorPart;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.multidiagram.extension.IEditorFactory;
import com.cea.papyrus.multidiagram.extension.MultiDiagramSharedObjects;


/**
 * Base class of Papyrus Editor factories.
 * Editor should subclass this class and provide a 0 args constructor initializing the super class.
 * @author dumoulin
 *
 */
public class PapyrusEditorFactory implements IEditorFactory {

	/**
	 * Expected Class of the diagram to create.
	 */
	private Class diagramClass;

	protected String expectedType;

	public PapyrusEditorFactory(Class diagramClass,  String expectedType) {
//		super(diagramClass, null);
		assert( expectedType!=null);
		this.diagramClass = diagramClass;
		this.expectedType = expectedType;
	}

	/**
	 * Check for a papyrus generated editor of type specified by this class.
	 */
	public boolean isEditorFor(Object root) {
		if( root instanceof Diagram )
		{
			Diagram diagram = (Diagram)root;
			final String type = diagram.getType();
			return expectedType.equals(type);
		}
		// no
		return false;
	}

	/**
	 * Create a new editor for the specified root object.
	 * @param sharedObjects
	 * @param root
	 * @return multidiagram.NestedDiagram
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws IllegalArgumentException 
	 */
	public IEditorPart createEditorFor(MultiDiagramSharedObjects sharedObjects, Object root)  
	{
		return createEditorFor((PapyrusMultiDiagramSharedObjects)sharedObjects, root);
	}
	
	/**
	 * Create a new editor for the specified root object.
	 * @param sharedObjects
	 * @param root
	 * @return multidiagram.NestedDiagram
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws IllegalArgumentException 
	 */
	public IEditorPart createEditorFor(PapyrusMultiDiagramSharedObjects sharedObjects, Object root)  
	{
		GraphicalEditor editor;

		try {
			// 	public ClassDiagramEditor( Diagram diagram, ModelManager modelMngr, CommandStack commandStack, ActionRegistry actionRegistry){//, ModelResourceManager resourceManager){
			Constructor<?> c = getDiagramClass().getConstructor(Diagram.class, ModelManager.class, CommandStack.class, ActionRegistry.class);
			editor = (GraphicalEditor)c.newInstance(root, sharedObjects.getModelMngr(), sharedObjects.getCommandStack(), sharedObjects.getActionRegistry());
			return editor;

		} catch (SecurityException e) {
			// Lets propagate. This is an implementation problem that should be solved by programmer.
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			// try with super
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			// Lets propagate. This is an implementation problem that should be solved by programmer.
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			// Lets propagate. This is an implementation problem that should be solved by programmer.
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			// Lets propagate. This is an implementation problem that should be solved by programmer.
			throw new RuntimeException(e);
		}
	}

	/**
	 * @return the diagramClass
	 */
	public Class getDiagramClass() {
		return diagramClass;
	}

	/**
	 * @return the expectedType
	 */
	public String getExpectedType() {
		return expectedType;
	}


}
